package com.googlecode.wickedforms.xvergabe;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;

import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.IChoiceRenderer;
import org.apache.wicket.markup.html.form.SubmitLink;
import org.apache.wicket.markup.html.form.TextArea;
import org.apache.wicket.markup.html.panel.FeedbackPanel;
import org.apache.wicket.model.CompoundPropertyModel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.model.StringResourceModel;
import org.apache.wicket.request.http.WebResponse;
import org.apache.wicket.util.io.IOUtils;
import org.apache.xmlbeans.XmlException;
import org.xvergabe.xsd.forms.components.x20.RoleType;

import com.googlecode.wickedforms.xvergabe.pdf.PdfExporter;
import com.googlecode.wickedforms.xvergabe.xml.FormXmlReader;
import com.googlecode.wickedforms.xvergabe.xml.FormXmlStreamReader;

public class HomePage extends BasePage {

	private final Preset selectedPreset = Preset.FORMBLATT_332_L_MIT_ULV;

	private final TextArea<String> xmlTextArea;

	private String xmlString;

	public HomePage() {

		IModel<FormParameters> model = new CompoundPropertyModel<FormParameters>(
				Model.of(createInitialFormParameters()));

		Form<FormParameters> form = new Form<FormParameters>("form", model) {

			@Override
			protected void onSubmit() {

				try {

					FormParameters parameters = getModelObject();
					parameters.setXml(xmlString);
					FormXmlReader xmlReader = new FormXmlStreamReader(
							new ByteArrayInputStream(parameters.getXml()
									.getBytes()));
					List<String> xmlValidationErrors = xmlReader.validate();

					if (!xmlValidationErrors.isEmpty()) {
						for (String error : xmlValidationErrors) {
							error(error);
						}
					} else {
						FormParameters formParameters = getModelObject();
						setResponsePage(new FormPage(formParameters));
					}
				} catch (IOException e) {
					error(e.getMessage());
				} catch (XmlException e) {
					error(e.getMessage());
				}
			}
		};

		add(new Label("sidebartext", new StringResourceModel("sidebartext",
				this, null).getObject()));
		form.add(new FeedbackPanel("feedback"));
		form.add(createModeChoice());
		form.add(createLocaleChoice());
		this.xmlTextArea = createXmlTextArea();
		this.xmlTextArea.setOutputMarkupId(true);
		form.add(this.xmlTextArea);
		form.add(createPresetChoice());
		updateXmlArea();

		SubmitLink pdfExportButton = new SubmitLink("pdfExport") {
			@Override
			public void onSubmit() {
				WebResponse response = (WebResponse) getRequestCycle()
						.getResponse();
				response.reset();
				response.setContentType("application/pdf");
				PdfExporter pdfExporter = new PdfExporter();
				pdfExporter.export(new StringReader(xmlString),
						response.getOutputStream());
			}
		};
		form.add(pdfExportButton);

		add(form);

	}

	private void updateXmlArea() {
		try {
			Reader reader = HomePage.this.selectedPreset.getReaderUtf8();
			StringWriter writer = new StringWriter();
			IOUtils.copy(reader, writer);
			HomePage.this.xmlTextArea.setModelObject(writer.toString());
		} catch (IOException e) {
			throw new RuntimeException(e);
		}

	}

	private FormParameters createInitialFormParameters() {
		try {
			FormParameters formParameters = new FormParameters();
			Reader reader = Preset.AUFFORDERUNG_ABGABE_ANGEBOT_VOL_A
					.getReaderUtf8();
			StringWriter writer = new StringWriter();
			IOUtils.copy(reader, writer);
			formParameters.setXml(writer.toString());
			return formParameters;
		} catch (IOException e) {
			throw new RuntimeException(e);
		}

	}

	private DropDownChoice<Locale> createLocaleChoice() {
		DropDownChoice<Locale> localeChoice = new DropDownChoice<Locale>(
				"locale", Arrays.asList(Locale.GERMAN, Locale.ENGLISH));
		localeChoice.setChoiceRenderer(new IChoiceRenderer<Locale>() {

			@Override
			public Object getDisplayValue(final Locale locale) {
				if (locale == Locale.GERMAN) {
					return "Deutsch";
				} else if (locale == Locale.ENGLISH) {
					return "Englisch";
				}
				throw new IllegalStateException("Unknown Locale: " + locale);
			}

			@Override
			public String getIdValue(final Locale value, final int index) {
				return "" + index;
			}
		});
		localeChoice.setRequired(true);
		return localeChoice;
	}

	private DropDownChoice<RoleType.Enum> createModeChoice() {

		List<RoleType.Enum> choices = new ArrayList<RoleType.Enum>();

		choices.add(RoleType.CONSUMER);
		choices.add(RoleType.PROVIDER);

		DropDownChoice<RoleType.Enum> modeChoice = new DropDownChoice<RoleType.Enum>(
				"displayMode", choices);

		modeChoice.setChoiceRenderer(new IChoiceRenderer<RoleType.Enum>() {

			@Override
			public Object getDisplayValue(final RoleType.Enum object) {
				if (object == RoleType.PROVIDER) {
					return "Vergabestelle";
				} else if (object == RoleType.CONSUMER) {
					return "Bieter";
				} else {
					throw new IllegalArgumentException("unknown role: "
							+ object.toString());
				}
			}

			@Override
			public String getIdValue(final RoleType.Enum object, final int index) {
				return String.valueOf(index);
			}
		});

		modeChoice.setRequired(true);
		return modeChoice;
	}

	private DropDownChoice<Preset> createPresetChoice() {
		DropDownChoice<Preset> choice = new DropDownChoice<Preset>("preset",
				new PropertyModel(this, "selectedPreset"), Arrays.asList(Preset
						.values()));
		choice.setChoiceRenderer(new IChoiceRenderer<Preset>() {

			@Override
			public Object getDisplayValue(final Preset object) {
				return object.getTitle();
			}

			@Override
			public String getIdValue(final Preset object, final int index) {
				return String.valueOf(index);
			}
		});

		choice.add(new AjaxFormComponentUpdatingBehavior("onchange") {
			@Override
			protected void onUpdate(final AjaxRequestTarget target) {
				updateXmlArea();
				target.add(HomePage.this.xmlTextArea);
			}
		});
		return choice;
	}

	private TextArea<String> createXmlTextArea() {
		TextArea<String> xmlArea = new TextArea<String>("xml",
				new PropertyModel<String>(this, "xmlString"));
		xmlArea.setRequired(true);
		return xmlArea;
	}

}
